//
//  ITTImageWallView.m
//  AiTuPianPad
//
//  Created by guo hua on 11-9-20.
//  Copyright (c) 2011年 __MyCompanyName__. All rights reserved.
//
#import <objc/runtime.h>
#import "ITTImageWallView.h"
#import "ITTImageCacheManager.h"

#define INDEXIVALID    -1
#define MAXCACHESIZE   10

enum tag {
    TAG_EMPTY_TIP = 300,
    TAG_LOADING_TIP,
};

@interface ITTImageWallView(private)
-(CGRect)frameForIndex:(NSInteger)index;
-(NSInteger)indexOfRect:(CGRect)rect;
-(NSRange)visibleRange;
-(BOOL)isVisibleAtIndex:(NSInteger)index;
-(BOOL)isShowingIndex:(NSInteger)index;
-(void)tileItems;
@end

@implementation ITTImageWallView
@synthesize wallDelegate = _wallDelegate,wallDataSource = _wallDataSource;
@synthesize imageContentMode;
@synthesize resizeType;
-(id)initWithFrame:(CGRect)frame{
    self = [super initWithFrame:frame];
    if (self) {
        if (!_visibleViews) {
            _visibleViews = [[NSMutableSet alloc] init];
        }
        if (!_recycledViews) {
            _recycledViews = [[NSMutableSet alloc] init];
        }
        self.delegate = self;
        self.resizeType = ITTImageResizeTypeNone;
    }
    return self;
}

-(void)dealloc{
    for (ITTImageWallItem *item in _visibleViews) {
        item.delegate = nil;
    }
    [_recycledViews release];
    _recycledViews = nil;
    [_visibleViews release];
    _visibleViews = nil;
    [super dealloc];
}

-(void)showEmpty:(BOOL)show{
    UIImageView *tip = (UIImageView *)[self viewWithTag:TAG_EMPTY_TIP];
    if (show) {
        [self showLoading:NO];
        if (!tip) {
            tip = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"empty_tip"]] autorelease];
        }
        tip.center = getCenterOfView(self);
        tip.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin|UIViewAutoresizingFlexibleRightMargin|UIViewAutoresizingFlexibleTopMargin|UIViewAutoresizingFlexibleBottomMargin;
        tip.tag = TAG_EMPTY_TIP;
        [self addSubview:tip];
    }else{
        [tip removeFromSuperview];
    }
}

-(void)showLoading:(BOOL)show{
    UIImageView *tip = (UIImageView *)[self viewWithTag:TAG_LOADING_TIP];
    if (show) {
        [self showEmpty:NO];
        if (!tip) {
            tip = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"loading_tip"]] autorelease];
        }
        tip.center = getCenterOfView(self);
        tip.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin|UIViewAutoresizingFlexibleRightMargin|UIViewAutoresizingFlexibleTopMargin|UIViewAutoresizingFlexibleBottomMargin;
        tip.tag = TAG_LOADING_TIP;
        [self addSubview:tip];
    }else{
        [tip removeFromSuperview];
    }
}

-(void)setWallDataSource:(id<ITTImageWallViewDataSource>)object{
    if (object == _wallDataSource) {
        return;
    }else{
        _wallDataSource = object;
        [self reloadData];
    }
}

-(void)reloadData{
    if (!_wallDataSource) {
        return;
    }
    if (!_visibleViews) {
        _visibleViews = [[NSMutableSet alloc] init];
    }
    if (!_recycledViews) {
        _recycledViews = [[NSMutableSet alloc] init];
    }
    for (UIView *view in _visibleViews) {
        [view removeFromSuperview];
    }
    [_visibleViews removeAllObjects];
    [_recycledViews removeAllObjects];
    itemCount = [_wallDataSource numberOfImageOnWall:self];
    if (itemCount>0) {
        [self showEmpty:NO];
        [self showLoading:NO];
    }
    numberPerRow = [_wallDataSource numberOfViewPerRowForWall:self];
    int row = itemCount/numberPerRow;
    if (itemCount%numberPerRow != 0) {
        row += 1;
    }
    
    rowHight = [_wallDataSource rowHightOfWallView:self];
    
    CGFloat contentHight = rowHight*row;
    if (contentHight<self.bounds.size.height) {
        contentHight = self.bounds.size.height;
    }
    self.contentSize = CGSizeMake(self.frame.size.width, contentHight);
    
    [self tileItems];
}

-(ITTImageWallItem *)dequeueReusableItemWithIdentifier:(NSString *)identifier{
    ITTImageWallItem *reuseItem = nil;
    for (ITTImageWallItem *item in _recycledViews) {
        if ([item.identifier isEqualToString:identifier]) {
            reuseItem = [item retain];
            break;
        }
    }
    if (reuseItem) {
        [_recycledViews removeObject:reuseItem];
    }
    return [reuseItem autorelease];
}

-(void)refreshView{
    if (!_wallDataSource) {
        return;
    }
    if (!_visibleViews) {
        _visibleViews = [[NSMutableSet alloc] init];
    }
    if (!_recycledViews) {
        _recycledViews = [[NSMutableSet alloc] init];
    }
    itemCount = [_wallDataSource numberOfImageOnWall:self];
    numberPerRow = [_wallDataSource numberOfViewPerRowForWall:self];
    int row = itemCount/numberPerRow;
    if (itemCount%numberPerRow != 0) {
        row += 1;
    }
    
    rowHight = [_wallDataSource rowHightOfWallView:self];
    self.contentSize = CGSizeMake(self.frame.size.width, rowHight*row);
    
    [self tileItems];
}

- (void)tileItems {
    if (!_wallDataSource) {
        return;
    }
    _visibleRange = [self visibleRange];
    for (ITTImageWallItem *item in _visibleViews) {
        if (![self isVisibleAtIndex:item.indexOnWall]) {
            [item removeFromSuperview];
            [item cancelImageRequest];
            item.indexOnWall = INDEXIVALID;
            item.imageUrl = nil;
            item.image = nil;
            item.delegate = nil;
            [_recycledViews addObject:item];
        }
    }
    [_visibleViews minusSet:_recycledViews];
    while ([_recycledViews count]> MAXCACHESIZE) {
        [_recycledViews removeObject:[_recycledViews anyObject]];
    }
    NSRange range = _visibleRange;
    for (int i = range.location; i<range.location+range.length; i++) {
        if (![self isShowingIndex:i]) {
            ITTImageWallItem *item = [_wallDataSource  imageWallView:self viewAtIndex:i];
            
            item.frame = [self frameForIndex:item.indexOnWall];
            
            item.layer.shadowOffset = CGSizeMake(5, 5);
            item.layer.shadowRadius = 6.0;
            item.layer.shadowColor = [UIColor blackColor].CGColor;
            item.layer.shadowOpacity = 0.8;
            
            item.indexOnWall = i;
            [self addSubview:item];
            
            item.alpha = 0;
            item.contentMode = imageContentMode;
            item.resizeType = resizeType;
            [item cancelImageRequest];

            [_visibleViews addObject:item];
            [item setDefaultImage:[UIImage imageNamed:@"default_image_news_top"]];
            [item enableImageBtn];
            item.delegate = self;
            [item loadImage:item.imageUrl];
            
            [UIView setAnimationDuration:1.0f];
            [UIView beginAnimations:nil context:nil];
            item.alpha = 1;
            [UIView commitAnimations];
        }
    }
    for (ITTImageWallItem *item in _visibleViews) {
        item.frame = [self frameForIndex:item.indexOnWall];
    }
}

-(CGRect)frameForIndex:(NSInteger)index{
    CGRect r = CGRectZero;
    int row = (index+1)/numberPerRow;
    int numberInRow = (index+1)%numberPerRow;
    if ((index+1)%numberPerRow == 0) {
        row -= 1;
        numberInRow = numberPerRow;
    }
    CGFloat paddingHight = 0;
    CGFloat paddingWidth = 0;
    CGFloat leftPadding  = 0;
    
    if (_wallDataSource&&[(id)_wallDelegate respondsToSelector:@selector(imageWallView:paddingHightOfRow:)]) {
        paddingHight = [_wallDataSource imageWallView:self paddingHightOfRow:row];
    }
    if (_wallDataSource&&[(id)_wallDataSource respondsToSelector:@selector(imageWallView:paddingWidthOfRow:)]) {
        paddingWidth = [_wallDataSource imageWallView:self paddingWidthOfRow:row];
    }
    if (_wallDataSource&&[(id)_wallDataSource respondsToSelector:@selector(imageWallView:leftPaddingOfRow:)]) {
        leftPadding = [_wallDataSource imageWallView:self leftPaddingOfRow:row];
    }
    if (_wallDataSource&&[(id)_wallDataSource respondsToSelector:@selector(imageWallView:viewSizeInRow:)]) {
        r.size = [_wallDataSource imageWallView:self viewSizeInRow:row];
    }else{
        r.size = CGSizeMake((self.bounds.size.width-leftPadding)/(numberPerRow) - paddingWidth, rowHight - 2*paddingHight);
    }
    
    r.origin.x = nearbyintf(leftPadding + (r.size.width + paddingWidth)*(numberInRow-1));
    r.origin.y = nearbyintf(paddingHight + row*rowHight);
    return r;
}

-(NSRange)visibleRange{
    rowHight = [_wallDataSource rowHightOfWallView:self];
    NSInteger startRow = (int)(self.contentOffset.y/rowHight) - 1;
    if (startRow<0) {
        startRow = 0;
    }
    NSInteger endRow = (int)((self.contentOffset.y+self.bounds.size.height)/rowHight)+1;
    int rowCount = itemCount/numberPerRow;
    if (itemCount%numberPerRow != 0) {
        rowCount += 1;
    }
    if (endRow > rowCount) {
        endRow = rowCount;
    }
    NSInteger start = numberPerRow*startRow;
    NSInteger end = numberPerRow*(endRow-startRow+1);
    if (end + start > itemCount) {
        end = itemCount - start;
    }
    return NSMakeRange(start,end);
}

-(BOOL)isVisibleAtIndex:(NSInteger)index{
    NSRange range = _visibleRange;//[self visibleRange];
    if (index >= range.location&&index < range.location+range.length) {
        return YES;
    }
    return NO;
}

- (void)imageClicked:(ITTImageView *)imageView{
    if (![imageView isKindOfClass:[ITTImageWallItem class]]) {
        return;
    }
    NSInteger index = [(ITTImageWallItem *)imageView indexOnWall];
    if ([self isShowingIndex:index]) {
        if (_wallDelegate&&[(id)_wallDelegate respondsToSelector:@selector(imageWallView:didselectAtIndex:)]) {
            [_wallDelegate imageWallView:self didselectAtIndex:index];
        }
    }
}

-(BOOL)isShowingIndex:(NSInteger)index{
    ITTImageWallItem *indexedItem = nil;
    for (ITTImageWallItem *item in _visibleViews) {
        if (item.indexOnWall==index) {
            indexedItem = item;
            break;
        }
    }
    if (indexedItem) {
        if (indexedItem.superview == self) {
            return YES;
        }else{
            [_visibleViews removeObject:indexedItem];
        }
    }
    return NO;
}

- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
	//[self setNeedsDisplay];
    [[ITTImageCacheManager sharedManager] suspendImageLoading];
    NSRange visibleRange = [self visibleRange];
    if (NSEqualRanges(visibleRange, _visibleRange)) {
        return;
    }else{
        [self tileItems];
    }
}

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{
    if (!decelerate) {
        [[ITTImageCacheManager sharedManager] restoreImageLoading];
    }
}

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{
    [[ITTImageCacheManager sharedManager] restoreImageLoading];
}

@end

